package main

import (
	"context"
	"fmt"
	"grpc-client/pb"
	"io"
	"log"
	"os"
	"time"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/metadata"
	"google.golang.org/protobuf/types/known/timestamppb"
)

const port = ":5001"

func main() {
	creds, err := credentials.NewClientTLSFromFile("cert.pem", "")

	if err != nil {
		log.Fatalln(err.Error())
	}

	options := []grpc.DialOption{grpc.WithTransportCredentials(creds)}

	conn, err := grpc.Dial("localhost"+port, options...)

	if err != nil {
		log.Fatalln(err.Error())
	}

	defer conn.Close()
	client := pb.NewEmployeeServiceClient(conn)

	// getByNo(client)
	// getAll(client)
	// addPhoto(client)
	saveAll(client)
}

func saveAll(client pb.EmployeeServiceClient) {

	employees := []pb.Employee{
		pb.Employee{
			Id:        400,
			No:        4001,
			FirstName: "Monica",
			LastName:  "Geller",
			MonthSalay: &pb.MonthSalay{
				Basic: 4000,
				Bonus: 1000,
			},
			Status: pb.EmployeeStatus_NORMAL,
			LastModified: &timestamppb.Timestamp{
				Seconds: time.Now().Unix(),
			},
		},
		pb.Employee{
			Id:        402,
			No:        4002,
			FirstName: "Joey",
			LastName:  "Tribbiani",
			MonthSalay: &pb.MonthSalay{
				Basic: 400,
				Bonus: 100,
			},
			Status: pb.EmployeeStatus_NORMAL,
			LastModified: &timestamppb.Timestamp{
				Seconds: time.Now().Unix(),
			},
		},
	}

	stream, err := client.SaveAll(context.Background())

	if err != nil {
		log.Fatalln(err.Error())
	}

	finishChannel := make(chan struct{})

	go func() {
		for {
			res, err := stream.Recv()

			if err == io.EOF {
				finishChannel <- struct{}{}
				break
			}

			if err != nil {
				log.Fatalln(err.Error())
			}

			fmt.Println(res.Employee)
		}
	}()

	for _, e := range employees {
		err := stream.Send(&pb.EmployeeRequest{Employee: &e})

		if err != nil {
			log.Fatalln(err.Error())
		}
	}

	stream.CloseSend()

	<-finishChannel

}

func addPhoto(client pb.EmployeeServiceClient) {

	imgFile, err := os.Open("school.jpg")

	if err != nil {
		log.Fatalln(err.Error())
	}

	defer imgFile.Close()

	md := metadata.New(map[string]string{"no": "2004"})

	context := context.Background()

	context = metadata.NewOutgoingContext(context, md)

	stream, err := client.AddPhoto(context)

	if err != nil {
		log.Fatalln(err.Error())
	}

	for {
		chunk := make([]byte, 128*1024)

		chunkSize, err := imgFile.Read(chunk)

		if err == io.EOF {
			break
		}

		if err != nil {
			log.Fatalln(err.Error())
		}

		if chunkSize < len(chunk) {
			chunk = chunk[:chunkSize]
		}

		stream.Send(&pb.AddPhotoRequest{Data: chunk})
		time.Sleep(time.Millisecond * 700)
	}

	res, err := stream.CloseAndRecv()

	if err != nil {
		log.Fatalln(err.Error())
	}

	fmt.Println(res.IsOk)

}

func getByNo(client pb.EmployeeServiceClient) {
	res, err := client.GetByNo(context.Background(), &pb.GetByNoRequest{No: 1999})
	if err != nil {
		log.Fatalln(err.Error())
	}
	fmt.Println(res)
}

func getAll(client pb.EmployeeServiceClient) {
	stream, err := client.GetAll(context.Background(), &pb.GetAllRequest{})

	if err != nil {
		log.Fatalln(err.Error())
	}

	for {
		res, err := stream.Recv()

		if err == io.EOF {
			break
		}

		if err != nil {
			log.Fatalln(err.Error())
		}

		fmt.Println(res.Employee)
	}

}
